<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>1.使用框架实现基本场景</title>
	<link rel="stylesheet" href="./index.css">
</head>

<body>
<canvas id="canvas"></canvas>
<script id="vertex-shader-3d" type="x-shader/x-vertex">
uniform mat4 u_worldViewProjection;
uniform vec3 u_lightWorldPos;
uniform mat4 u_world;
uniform mat4 u_viewInverse;
uniform mat4 u_worldInverseTranspose;

attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

void main() {
  v_texCoord = a_texcoord;
  v_position = (u_worldViewProjection * a_position);
  v_normal = (u_worldInverseTranspose * vec4(a_normal, 0)).xyz;
  v_surfaceToLight = u_lightWorldPos - (u_world * a_position).xyz;
  v_surfaceToView = (u_viewInverse[3] - (u_world * a_position)).xyz;
  gl_Position = v_position;
}
</script>
<script id="fragment-shader-3d" type="x-shader/x-fragment">
precision mediump float;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

uniform vec4 u_lightColor;
uniform vec4 u_colorMult;
uniform sampler2D u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_specularFactor;

vec4 lit(float l ,//点光大小
float h,//高光大小
 float m) {
  return vec4(1.0,abs(l),(l > 0.0) ? pow(max(0.0, h), m) : 0.0,//如果有点光返回h或者0
              1.0);
}

void main() {
  vec4 diffuseColor = texture2D(u_diffuse, v_texCoord);//纹理
  vec3 a_normal = normalize(v_normal);//法线
  vec3 surfaceToLight = normalize(v_surfaceToLight);//光线到顶点向量
  vec3 surfaceToView = normalize(v_surfaceToView);//地对空方向
  vec3 halfVector = normalize(surfaceToLight + surfaceToView);//光线和法线中间值
  vec4 litR = lit(dot(a_normal, surfaceToLight),
                    dot(a_normal, halfVector), u_shininess);
  vec4 outColor = vec4((
  u_lightColor * (diffuseColor * litR.y * u_colorMult +//光线颜色和大小
                u_specular * litR.z * u_specularFactor)).rgb,//高光
      diffuseColor.a);//透明度
  gl_FragColor = outColor;
}
</script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/primitives.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/texture-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/chroma.min.js"></script>
<script>
const canvas = document.querySelector("#canvas");
const gl = canvas.getContext("webgl");

webglUtils.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

// Clear the canvas AND the depth buffer.
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);

//获取program,获取着色器变量
const program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
const uniformSetters = webglUtils.createUniformSetters(gl, program);
const attribSetters  = webglUtils.createAttributeSetters(gl, program);
//获取模型
var buffers = window.primitives.createSphereBuffers(gl, 18, 48, 48);
//材质制作
var textures = textureUtils.makeStripeTexture(gl, { color1: "#FFF", color2: "#FFF", })

const camera={
	position:[0,0,100],
	target:[0,0,0],
	up:[0, 1, 0],
	matrix:m4.identity()
}
const model={
	radius: 100,
	position:[0,0,0],
    a_position: { buffer: buffers.position, numComponents: 3, },
    a_normal:   { buffer: buffers.normal,   numComponents: 3, },
    a_texcoord: { buffer: buffers.texcoord, numComponents: 2, },
	materialUniforms: {
		u_colorMult:             [1,0,0,1],
		u_diffuse:               textures,
		u_specular:              [1, 1, 1, 1],
		u_shininess:             100,
		u_specularFactor:        0.8,
	}
}
const light={
	u_lightWorldPos:         [-50, 30, 100],
	u_lightColor:            [1, 0, 0, 1],
};
var worldUniforms = {
	u_worldViewProjection:   m4.identity(),
	u_world:                 m4.identity(),
	u_worldInverseTranspose: m4.identity(),
};
function degToRad(d) {
    return d * Math.PI / 180;
}
//设置相机和投影
var projectionMatrix =m4.perspective(degToRad(60), gl.canvas.clientWidth / gl.canvas.clientHeight, 1, 2000);
var cameraMatrix = m4.lookAt(camera.position, camera.target, camera.up, camera.matrix);
var viewMatrix = m4.inverse(cameraMatrix);
var viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);

//获取模型在世界的模型位置并转置
var worldMatrix = m4.translation(...model.position);
worldUniforms.u_world = worldMatrix;
m4.multiply(viewProjectionMatrix, worldMatrix, worldUniforms.u_worldViewProjection);//和视图矩阵相乘获取u_worldViewProjection
m4.transpose(m4.inverse(worldMatrix), worldUniforms.u_worldInverseTranspose);
//开始设置着色器变量
gl.useProgram(program);

webglUtils.setAttributes(attribSetters, model);//设置模型
webglUtils.setUniforms(uniformSetters, {
	...model.materialUniforms,//设置模型材质
	...worldUniforms,//设置世界变量
	...light,//设置光
	u_viewInverse:camera.matrix//设置视图矩阵u_viewInverse
});
gl.drawElements(gl.TRIANGLES, buffers.numElements, gl.UNSIGNED_SHORT, 0);
</script>
</body>

</html>